Word ladder II¶
Time: O(NxD); Space: O(D); hard
Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that: 1. Only one letter can be changed at a time 2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
Notes:
Return an empty list if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
You may assume no duplicates in the word list.
You may assume beginWord and endWord are non-empty and are not the same.
Example 1:
Input: beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
Output:
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Explanation * “hit”->“hot”->“dot”->“dog”->“cog” * “hit”->“hot”->“lot”->“log”->“cog” * The dictionary order of the first sequence is less than that of the second.
Example 2:
Input: beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”]
Output: []
Explanation:
The endWord “cog” is not in wordList, therefore no possible transformation
[1]:
from collections import defaultdict
from string import ascii_lowercase
class Solution1(object):
"""
Time: O(N*D), N is length of string, D is size of dictionary
Space: O(D)
"""
def findLadders(self, beginWord, endWord, wordList):
"""
:type beginWord: str
:type endWord: str
:type wordList: List[str]
:rtype: List[List[str]]
"""
dictionary = set(wordList)
result, cur, visited, found, trace = [], [beginWord], set([beginWord]), False, defaultdict(list)
while cur and not found:
for word in cur:
visited.add(word)
next = set()
for word in cur:
for i in range(len(word)):
for c in ascii_lowercase:
candidate = word[:i] + c + word[i + 1:]
if candidate not in visited and candidate in dictionary:
if candidate == endWord:
found = True
next.add(candidate)
trace[candidate].append(word)
cur = next
if found:
self.backtrack(result, trace, [], endWord)
return result
def backtrack(self, result, trace, path, word):
if not trace[word]:
result.append([word] + path)
else:
for prev in trace[word]:
self.backtrack(result, trace, [word] + path, prev)
[3]:
s = Solution1()
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
assert s.findLadders(beginWord, endWord, wordList) == [
["hit","hot","lot","log","cog"],
["hit","hot","dot","dog","cog"]
]
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
assert s.findLadders(beginWord, endWord, wordList) == []